﻿using System;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace Anno.Util
{
    public class Windows
	{
		/// <summary>
		/// 
		/// </summary>
		public string Output { get; private set; }

		/// <summary>
		/// 
		/// </summary>
		public string[] Lines
		{
			get
			{
				string output = this.Output;
				if (output == null)
				{
					return null;
				}
				return output.Split(Environment.NewLine.ToCharArray());
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public int ExitCode { get; private set; }

		/// <summary>
		/// 
		/// </summary>
		public string ErrorMsg { get; private set; }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="workingDirectory"></param>
		/// <param name="redirect"></param>
		/// <returns></returns>
		/// <exception cref="Exception"></exception>
		public BashResult Command(string input, string workingDirectory, bool redirect)
		{
			if (Bash.Native)
			{
				throw new Exception("请切换到Linux.");
			}
			int id = 0;
			using (Process process = new Process
			{
				StartInfo = this.BashInfo(input, workingDirectory, redirect)
			})
			{
				process.Start();
				id = process.Id;
				if (!redirect)
				{
					this.Output = null;
					this.ErrorMsg = null;
				}
				if (process.WaitForExit(1000))
				{
					this.ExitCode = process.ExitCode;
				}
				process.Close();
			}
			if (redirect)
			{
				return new BashResult(this.Output, this.ErrorMsg, this.ExitCode, id);
			}
			return new BashResult(null, null, this.ExitCode, id);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="workingDirectory"></param>
		/// <returns></returns>
		public BashResult StartProcess(string input, string workingDirectory)
		{
			Process process = null;
			try
			{
				input = input.Trim();
				int num = input.IndexOf(" ");
				string text = (num == -1) ? input : input.Substring(0, num);
				string text2 = input.Substring(num);
				string text3 = Path.Combine(workingDirectory, text);
				if (!File.Exists(text3))
				{
					text3 = text;
				}
				process = Process.Start(new ProcessStartInfo
				{
					FileName = text3,
					Arguments = text2.TrimStart(),
					WorkingDirectory = workingDirectory,
					CreateNoWindow = true,
					WindowStyle = ProcessWindowStyle.Hidden,
					RedirectStandardOutput = true,
					RedirectStandardError = true
				});
			}
			catch (Exception ex)
			{
				return new BashResult(null, ex.Message, -1, -1);
			}
			return new BashResult(null, null, this.ExitCode, process.Id);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="pid"></param>
		public void KillProcessAndChildren(int pid)
		{
			if (pid < 0)
			{
				return;
			}
			try
			{
#if NETFRAMEWORK
				foreach (var managementBaseObject in new System.Management.ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid.ToString()).Get())
				{
					var managementObject = (System.Management.ManagementObject)managementBaseObject;
					this.KillProcessAndChildren(Convert.ToInt32(managementObject["ProcessID"]));
				}
#endif
				Process.GetProcessById(pid).Kill();
			}
			catch (Exception)
			{
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="redirect"></param>
		/// <returns></returns>
		public BashResult Command(string input, bool redirect)
		{
			return this.Command(input, null, redirect);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public BashResult Command(string input)
		{
			return this.Command(input, true);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="workingDirectory"></param>
		/// <param name="redirectOutput"></param>
		/// <returns></returns>
		private ProcessStartInfo BashInfo(string input, string workingDirectory, bool redirectOutput)
		{
			Console.InputEncoding = Encoding.UTF8;
			ProcessStartInfo processStartInfo = new ProcessStartInfo
			{
				FileName = Bash._bashPath,
				Arguments = "/c \"" + input + "\"",
				RedirectStandardInput = redirectOutput,
				RedirectStandardOutput = redirectOutput,
				RedirectStandardError = redirectOutput,
				UseShellExecute = false,
				CreateNoWindow = true,
				ErrorDialog = false
			};
			if (!string.IsNullOrWhiteSpace(workingDirectory))
			{
				processStartInfo.WorkingDirectory = workingDirectory;
			}
			return processStartInfo;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="redirect"></param>
		/// <returns></returns>
		public BashResult Echo(string input, bool redirect = false)
		{
			return this.Command("echo " + input, redirect);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="flags"></param>
		/// <param name="redirect"></param>
		/// <returns></returns>
		public BashResult Echo(string input, string flags, bool redirect = false)
		{
			return this.Command("echo " + flags + " " + input, redirect);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="redirect"></param>
		/// <returns></returns>
		public BashResult Echo(object input, bool redirect = false)
		{
			return this.Command(string.Format("echo {0}", input), redirect);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		/// <param name="flags"></param>
		/// <param name="redirect"></param>
		/// <returns></returns>
		public BashResult Echo(object input, string flags, bool redirect = false)
		{
			return this.Command(string.Format("echo {0} {1}", flags, input), redirect);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="redirect"></param>
		/// <returns></returns>
		public BashResult Dir(bool redirect = true)
		{
			return this.Command("dir", redirect);
		}

		/// <summary>
		/// cmd命令
		/// </summary>
		/// <param name="fileName"></param>
		/// <param name="args"></param>
		/// <returns></returns>
		public static string Cmd(string fileName, string args)
		{
			string output = string.Empty;
			var info = new ProcessStartInfo
			{
				FileName = fileName,
				Arguments = args,
				RedirectStandardOutput = true
			};
			using (var process = Process.Start(info))
			{
				output = process.StandardOutput.ReadToEnd();
			}
			return output;
		}
	}
}
